#include "BlockQueue.hpp"
#include "Task.hpp"
#include <ctime>


template<class C, class S>
class block_queues
{
public:
    block_queues(){}
    block_queues(BlockQueue<C>* c, BlockQueue<S>* s):c_(c), s_(s){}
public:
    BlockQueue<C>* c_;
    BlockQueue<S>* s_; 
};

void* consumer(void* bq)//消费者
{
    BlockQueue<CalTask>* c_bq_ = static_cast<block_queues<CalTask, SaveTask> *>(bq)->c_;
    BlockQueue<SaveTask>* s_bq_ = static_cast<block_queues<CalTask, SaveTask> *>(bq)->s_;
    while(true)
    {
        CalTask ct;
        c_bq_->pop(&ct);
        std::string result = ct();
        std::cout << "消费者消费：" << result << std::endl; 

        SaveTask st(result);
        
        s_bq_->push(st);
    }
    return nullptr;
}

void* producter(void* bq)//生产者
{
    BlockQueue<CalTask>* c_bq_ = static_cast<block_queues<CalTask, SaveTask> *>(bq)->c_;
    while(true)
    {
        int x = rand() % 10;
        int y = rand() % 5;
        char opt = math[rand() % math.size()];
        CalTask t(x, y, mycal, opt);
        c_bq_->push(t);
        std::cout << "生产者生产: " << t.toTaskString() << std::endl;
    }
    return nullptr;
}

void* saver(void* bq)//存储者
{
    BlockQueue<SaveTask>* s_bq_ = static_cast<block_queues<CalTask, SaveTask> *>(bq)->s_;
    while(true)
    {
        std::string path = "./log.txt";
        FILE* fp = fopen(path.c_str(), "a+");
        SaveTask st;
        s_bq_->pop(&st);
        std::string message = st.get_message();
        fwrite(message.c_str(), sizeof(char), message.size(),fp);
        fputs("\n",fp);
        std::cout << "存储者存储......" << std::endl;
        fclose(fp);
    }
    return nullptr;
}

int main()
{
    srand((unsigned int)time(nullptr));

    block_queues<CalTask, SaveTask> bqs;
    bqs.c_ = new BlockQueue<CalTask>();
    bqs.s_ = new BlockQueue<SaveTask>();

    pthread_t c, p, s;
    // pthread_t c, p;
    pthread_create(&p, nullptr, producter, (void*)&bqs);
    pthread_create(&c, nullptr, consumer, (void*)&bqs);
    pthread_create(&s, nullptr, saver, (void*)&bqs);

    pthread_join(p, nullptr);
    pthread_join(c, nullptr);
    pthread_join(s, nullptr);

    delete bqs.c_;
    delete bqs.s_;

    return 0;
}
pthread_rwlock_t t;